import time
from binance_exchange import *
from gate_exchange import *
from util.mysql_utils import *
import logging


class deal_task:
    def __init__(self,futures_symbol,spot_symboy,each_order_usdt,total_order_usdt,open_chae,futures_order_type,spot_order_type,deal_type):
        self.futures_symbol = futures_symbol
        self.spot_symboy = spot_symboy
        self.each_order_usdt = each_order_usdt
        self.total_order_usdt = total_order_usdt
        self.open_chae = open_chae
        self.futures_order_type = futures_order_type
        self.spot_order_type = spot_order_type
        self.deal_type = deal_type


class funding_rate_deal:
    def __init__(self,my_sql_utils:mysql_utils,binance_futers_exchange:binance_exchange,gate_spot_exchange:gate_exchange):
        # 初始化两个交易所对象
        # 订阅交易对信息
        self.my_sql_utils = my_sql_utils
        self.binance_futers_exchange = binance_futers_exchange
        self.gate_spot_exchange = gate_spot_exchange
        # 添加logger
        self.logger = logging.getLogger("funding_rate_deal")
        
    # 建议添加清理资源的方法
    def cleanup(self):
        # 清理websocket连接等资源
        pass
        
    # 建议添加交易状态检查方法
    def check_order_status(self, futures_order_id, spot_order_id):
        pass

    def process_place_order(self,deal_task_data:deal_task):
        try:
            binance_account_val_check = self.check_postion_val(deal_task_data)
            if binance_account_val_check:
                # 获取下单时的价格
                futures_depth = self.binance_futers_exchange.get_depth(deal_task_data.futures_symbol)
                spot_depth = self.gate_spot_exchange.get_depth(deal_task_data.spot_symboy)
                
                # 计算下单数量
                order_amount = self.cal_order_amount(deal_task_data)
                
                # 下单
                futures_order = self.binance_futers_exchange.place_order_market(
                    deal_task_data.futures_symbol,
                    deal_task_data.futures_order_type,
                    order_amount
                )
                spot_order = self.gate_spot_exchange.create_order(
                    deal_task_data.spot_symboy,
                    deal_task_data.spot_order_type,
                    order_amount
                )
                
                if futures_order and spot_order:
                    # 准备插入数据
                    sql = """
                    INSERT INTO himalaya_funding_rate_straddle_detail 
                    (futures_symbol, spot_symbol, futures_open_price, spot_open_price, 
                    open_amount, futures_open_order_id, spot_open_order_id, straddle_id)
                    VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
                    """
                    
                    params = (
                        deal_task_data.futures_symbol,
                        deal_task_data.spot_symboy,
                        float(futures_depth['b'][0][0]),  # futures_open_price
                        float(spot_depth['result']['asks'][0][0]),  # spot_open_price
                        order_amount,
                        str(futures_order['orderId']),
                        str(spot_order['id']),
                        deal_task_data.deal_type  # 假设deal_type就是straddle_id
                    )
                    
                    # 保存到数据库
                    self.my_sql_utils.execute(sql, params)
                    self.logger.info(f"订单保存成功: futures_order_id={futures_order['orderId']}, spot_order_id={spot_order['id']}")
                    
                    return futures_order, spot_order
                
        except Exception as e:
            self.logger.error(f"下单或保存订单失败: {str(e)}")
            return None, None


    #计算下单数量，exchange_type  1 binacne  2 gate
    def cal_order_amount(self,deal_task_data:deal_task):
        buy1 = self.binance_futers_exchange.get_depth(deal_task_data.futures_symbol)['b'][0][0]
        amount = deal_task_data.each_order_usdt / float(buy1)
        return round(amount, 8)


    def check_postion_val(self,deal_task_data:deal_task):
        # 缺少对输入参数的基本验证
        if not deal_task_data:
            return False
        
        # 缺少对each_order_usdt和total_order_usdt的合法性检查
        if deal_task_data.each_order_usdt <= 0 or deal_task_data.total_order_usdt <= 0:
            return False

        #获取账户余额 要从 websocket 获取不能调用 api

        #多做一个检查 ，币价如果大于单笔金额 程序不支持开单  因为  后面下单  计算数量 会取整数


        #检查 币安
        positions = self.binance_futers_exchange.get_all_positions()

        available_usdt_balance = self.binance_futers_exchange.get_account_info("USDT")

        all_positions_val_binance = 0.0
        for position in positions:
            positionInitialMargin = float(position['positionInitialMargin'])
            all_positions_val_binance += positionInitialMargin
            if position['symbol'] == deal_task_data.futures_symbol:
                #已经超过单币  持仓限制
                if deal_task_data.total_order_usdt <= positionInitialMargin:
                    return False

        if all_positions_val_binance >= available_usdt_balance:
            return False

        #检查 gate
        available_usdt_gate = self.gate_spot_exchange.get_account("USDT")
        all_positions_gate =  self.gate_spot_exchange.get_all_accounts()
        all_positions_val_gate = 0.0

        for gate_position in all_positions_gate:
            if gate_position['currency'] != 'USDT':
                available = float(gate_position['available'])
                all_positions_val_gate += available
            else:
                if gate_position['currency'] == deal_task_data.spot_symboy.split('_')[0]:
                    available = float(gate_position['available'])
                    if deal_task_data.total_order_usdt <= available:
                        return False


        if all_positions_val_gate >= available_usdt_gate:
            return False

        return True









if __name__ == "__main__":
    my_sql_utils = mysql_utils("rm-bp1b1tq642t1mu232to.mysql.rds.aliyuncs.com",
                               3306,
                               "joyingbox_admin",
                               "geek@admin2024",
                               "himalaya")
    binace_key = "3S4j9rBxss0KBivifkgMMEykgWad9GEMl9hdgMhViiwKGNDy5NoLkYHIDg6K3VU5"
    binace_secret = "NzWj2BnVToddcO39tkJp7N1Xz041EYwzgVibMV7czf0ZaHWfuCM8GHnO8pBp03xH"
    binace_futures_exchange = binance_exchange(binace_key, binace_secret)

    gate_key = "3e8bf1c102bedfdea327212db1b466be"
    gate_secret = "d8d6024fa11a053f71d7dd20c1ce0713335d0b4e88e80ba11a844c00684e1d84"
    gate_spot_exchange = gate_exchange(gate_key, gate_secret)
    # 监控数据 交易信息
    task_list = my_sql_utils.query("SELECT * from himalaya_funding_rate_straddle_exchange where order_status = 0")
    # print(task_list)
    frd = funding_rate_deal(my_sql_utils,binace_futures_exchange,gate_spot_exchange)


    task = task_list[0]

    deal_task_data = deal_task(task[1],task[2],task[3],task[4],task[8],task[9],task[10],task[11])

    # frd.process_place_order(deal_task_data)
    # frd.check_postion_val(deal_task_data,"MEUSDT")


    #
    task = task_list[0]
    # futures_symbol = task[1]  # 期货标的
    # spot_symboy = task[2]  # 现货标的
    # each_order_usdt = task[3]  # 每笔下单金额
    # total_order_usdt = task[4] #总仓位
    # open_chae = task[8]  # 开仓差额
    # futures_order_type = task[9]
    # spot_order_type = task[10]
    # deal_type = task[11]

    deal_task_data = deal_task(task[1],task[2],task[3],task[4],task[8],task[9],task[10],task[11])

    binace_futures_exchange.subscribe(deal_task_data.futures_symbol)
    gate_spot_exchange.subscribe_depth_message(deal_task_data.spot_symboy)
    time.sleep(3)

    while True:
        #监控币 之间差额
        #bids  买单    ask  卖单

        try:
            future_depth = binace_futures_exchange.get_depth(deal_task_data.futures_symbol)
            spot_depth = gate_spot_exchange.get_depth(deal_task_data.spot_symboy)
            future_buy1 = float(future_depth['b'][0][0])
            spot_sell1 = float(spot_depth['result']['asks'][0][0])
            #实时差额
            now_time_cha_e = abs((future_buy1-spot_sell1)/future_buy1)
            if deal_task_data.open_chae >= now_time_cha_e:
                # frd.process_place_order(deal_task_data)
                pass

            print(f"symbol {deal_task_data.futures_symbol}  future_buy1 :{future_buy1}  spot_sell1 ： {spot_sell1}   chae {future_buy1 - spot_sell1}   chae%  {((future_buy1-spot_sell1)/future_buy1)-1}")
            # print(f"future_depth :{json.dumps(future_depth)}")
        except depth_update_exception as e:
            print(f"call chae exception")
            # print(f"spot_depth :{json.dumps(spot_depth)}")
            # print(f"future_depth :{json.dumps(future_depth)}")




        time.sleep(0.1)
